home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
usenet
/
sources
/
volume2
/
util
/
dres.2
< prev
next >
Wrap
Text File
|
1988-10-25
|
52KB
|
2,070 lines
Path: xanth!nic.MR.NET!umn-d-ub!rutgers!mailrus!ulowell!page
From: page@swan.ulowell.edu (Bob Page)
Newsgroups: comp.sources.amiga
Subject: v02i017: dres - an object-oriented resource library, Part02/03
Message-ID: <9822@swan.ulowell.edu>
Date: 25 Oct 88 00:55:00 GMT
Organization: University of Lowell, Computer Science Dept.
Lines: 2059
Approved: page@swan.ulowell.edu
Submitted-by: dillon@cory.berkeley.edu (Matt Dillon)
Posting-number: Volume 2, Issue 17
Archive-name: util/dres.2
# This is a shell archive. Remove anything before this line
# then unpack it by saving it in a file and typing "sh file"
# (Files unpacked will be owned by you and have default permissions).
# This archive contains the following files:
# notinlib/graph.c
# notinlib/ioctl.c
# notinlib/muldiv.asm
# src/qint.asm
# src/ires.h
# src/lists.asm
# src/timedate.c
# src/oldfile.c
# src/oldfile.h
# src/res.c
#
if `test ! -d notinlib`
then
mkdir notinlib
echo "mkdir notinlib"
fi
if `test ! -s notinlib/graph.c`
then
echo "writing notinlib/graph.c"
cat > notinlib/graph.c << '\Rogue\Monster\'
/*
* GRAPH.C
*/
#define GRAPH struct _GRAPH
#define GNODE struct _GNODE
#define GCTRL struct _GCTRL
/*
* Flags field: The upper 4 bits are copied to the lower 4 bits after
* the flags are processed, allowing for 'temporary'
* conditions.
*
* FL_SKIP Propogate a skip condition. As soon as the next node
* is ready to begin processing, cause it not to run
* its function and propogate the FL_SKIP to all of its
* children, and all of their children, etc...
*
* FL_SRC Infinite source, this arc is always ready with the
* given value.
*/
GLINK {
MINNODE FNode; /* link from, list based at node */
MINNODE TNode; /* link to, list based at node */
GNODE *FGNode; /* from this node */
GNODE *TGNode; /* to this node */
long FromId; /* Identify value slot for source */
long ToId; /* Identify value slot for destination */
long Value; /* value to pass to 'to' node */
ubyte Ready; /* value pending, else no value pending*/
ubyte Flags; /* FL_SKIP,FL_NULL,FL_SRC */
ubyte XFlags; /* XL_READ */
ubyte filler;
};
GNODE {
MINNODE GNode; /* master list node */
GRAPH *Graph; /* owning graph */
APTR Func; /* Function */
long Arg; /* Argument */
short WaitCnt; /* # parents who are not ready */
MINLIST ChildList; /* list of children */
MINLIST ParentList; /* list of parents */
MINLIST WakeUpList; /* WakeUp tasks waiting for an ARC to clear */
};
GRAPH {
MINLIST GNodes; /* list of all graphs in node */
long A45[2]; /* global base registers */
long UsrLen;
};
GRAPH *
AllocGraph(usrdatalen)
{
GRAPH *graph = AllocMem(sizeof(GRAPH), MEMF_PUBLIC|MEMF_CLEAR);
NewList(&graph->GNodes);
graph->a45[0] = A4;
graph->a45[1] = A5;
graph->UsrLen = usrdatalen;
}
GNODE *
AllocGraphNode(graph, func, arg, usrdata/NULL)
GRAPH *graph;
long arg;
{
GNODE *gnode = AllocMem(sizeof(GNODE), MEMF_PUBLIC|MEMF_CLEAR);
AddTail(&graph->GNodes, &gnode->GNode);
gnode->Graph = graph;
gnode->Func = func;
gnode->Arg = arg;
NewList(&gnode->ChildList);
NewList(&gnode->ParentList);
NewList(&gnode->WakeUpList);
}
/*
* Remove all arcs and free a graph node
*/
FreeGraphNode(gnode)
GNODE *gnode;
{
Forbid();
Remove(gnode);
while (glink = GetHead(&gnode->ChildList))
RemGraphArc(gnode, glink->FGTNode);
while (glink = GetHeadOff(&gnode->ParentList, 8))
RemGraphArc(glink->FGFNode, gnode);
Permit();
FreeMem(gnode, sizeof(GNODE));
};
FreeGraph(graph)
GRAPH *graph;
{
Forbid();
while (gnode = GetHead(&graph->GNodes))
FreeGraphNode(gnode);
Permit();
FreeMem(graph, sizeof(GRAPH));
}
/*
* Set the user data for a given node. The data is copied into an
* equivalent buffer for the node.
*/
SetUserData(gnode, usrdata/NULL)
GNODE *gnode;
{
}
/*
* Add a directed arc to the graph. Set the arc to 'not ready' and
* increment the child node's WaitCnt
*/
AddGraphArc(from, to)
GNODE *from, *to;
{
GLINK *glink = AllocMem(sizeof(GLINK), MEMF_PUBLIC);
Forbid();
AddTail(&from->ChildList, &glink->FNode);
AddTail(&to->ParentList, &glink->TNode);
glink->FGNode = from;
glink->FTNode = to;
++to->WaitCnt;
Permit();
}
chklink(glink, gnode)
GLINK *glink;
GNODE *gnode;
{
if (glink->TGNode == gnode)
return(glink);
return(NULL);
}
RemGraphArc(from, to)
GNODE *from, *to;
{
GLINK *glink;
Forbid();
if (glink = SearchFwdNode(GetHead(&from->ChildList), chklink, 0, to)) {
Remove(&glink->FNode);
Remove(&glink->TNode);
if (!glink->Ready) {
if (--to->WaitCnt == 0 && GetHeadOff(&to->ParentList, 8))
GHandler(to);
}
}
Permit();
}
SetGNodeFunc(gnode, func)
GNODE *gnode;
APTR func;
{
gnode->Func = func;
}
SetGNodeArg(gnode, arg)
GNODE *gnode;
{
gnode->Arg = arg;
}
APTR
GetGNodeFunc(gnode)
GNODE *gnode;
{
return(gnode->Func);
}
long
GetGNodeArg(gnode)
GNODE *gnode;
{
return(gnode->Arg);
}
/*
* This function may ONLY be called by a node function, and retrieves
* the value from one of the parent arcs (arcs comming in). When the
* node function returns, any remaining unread parent arc's values will
* be discarded.
*/
long
GetArcValue(ToId)
{
}
/*
* This function may ONLY be called by a node function, and sets the
* result value to one of its child arcs (arcs going out). When the
* node function returns, any remaining unset child arc's values will
* be SKIPd.
*
* NOTE! This function will block on child nodes which have yet to
* read the previous value with GetArcValue() or are still running.
*/
SetArcValue(gnode, FromId, flags)
GNODE *gnode;
{
}
/*
* This function may be called by anybody, and forces a value into an
* arc. This function is usually used to 'prime' a graph.
*/
PrimeArc(from, to, value)
GNODE *from, *to;
{
}
/*
* GetGraph()
*
* Load the two buffers with entries corrosponding to the graph. arcen
* and nodeen initially contain the number of ARC and NODE structure
* entries that have been allocated. These variables will hold the
* actual number of ARC and NODE entries in the graph regardless of
* whether the operation succeeds.
*
* 0 is returned if the operation does not succeed, 1 if it does.
* The size of the node structure depends on the size of attached
* user information.
*
* ARC structure: two words / entry, representing an arc (from, to),
* where each word is an index (by entry #) into nodebuf.
* i.e. 0, 1, 2 ... even if usrdatalen is 0.
*
* NODE structure: any user data that has been applied to the node, as
* specified by AllocGraphNode().
*/
GetArcs(graph, arcbuf, &arcen, nodebuf, &nodeen)
GRAPH *graph;
{
}
\Rogue\Monster\
else
echo "will not over write notinlib/graph.c"
fi
if [ `wc -c notinlib/graph.c | awk '{printf $1}'` -ne 5849 ]
then
echo `wc -c notinlib/graph.c | awk '{print "Got " $1 ", Expected " 5849}'`
fi
if `test ! -s notinlib/ioctl.c`
then
echo "writing notinlib/ioctl.c"
cat > notinlib/ioctl.c << '\Rogue\Monster\'
/*
*FUNC= IoCreate D0/D1/A0
*FUNC= IoDelete D0
*FUNC= IoOpen D0/D1/A0
*FUNC= IoClose A0
;FUNC= IoCtl D0/D1/D2/A0
*FUNC= NULL -
*FUNC= NULL -
*FUNC= NULL -
*FUNC= NULL -
*FUNC= NULL -
*FUNC= NULL -
*FUNC= NULL -
*/
#include <local/typedefs.h>
#include <local/ioctl.h>
typedef long (*FPTR)();
#define HAN struct _HAN
#define MHAN struct _MHAN
#define HANSIZE 8
HAN {
long Reserved;
MHAN *MHan; /* Related MHandle */
/* USER STRUCTURE */
};
MHAN {
NODE Node;
long (*IoCtlFunc)(); /* Control Function / NULL */
uword Refs; /* Total References */
uword HanSize; /* Size of a HANdle */
};
#asm
MHA_IOCTLFUNC equ 14
#endasm
static MLIST MList = { (MNODE *)&MList.mlh_Tail, NULL, (MNODE *)&MList.mlh_Head };
static long Lock[2] = { 0,0 };
lIoCreate(name, func, hansize)
char *name;
long (*func)();
{
register MHAN *mh;
long res = -1;
hansize += HANSIZE;
LockAddr(Lock);
for (mh = GetHead(&MList); mh; mh = GetSucc(mh)) {
if (strcmp(name, mh->Node.ln_Name) == 0)
goto fail;
}
if ((mh = AllocMem(sizeof(MHAN), MEMF_PUBLIC|MEMF_CLEAR)) == NULL)
goto fail;
if ((mh->Node.ln_Name = AllocMem(strlen(name)+1, MEMF_PUBLIC)) == NULL) {
FreeMem(mh, sizeof(MHAN));
goto fail;
}
strcpy(mh->Node.ln_Name, name);
mh->IoCtlFunc = func;
mh->HanSize = HANSIZE + hansize;
AddHead(&MList, mh);
fioctl(func, _IOC_CREATE, NULL, 0);
res = 0;
fail:
UnLockAddr(Lock);
return(res);
}
/*
* Delete an IO device. The device's name is removed from the nameslist
* and any further non-internal IoCtl's on active connections will return
* -1.
*/
lIoDelete(name)
char *name;
{
register MHAN *mh;
long (*func)();
LockAddr(Lock);
for (mh = GetHead(&MList); mh; mh = GetSucc(mh)) {
if (mh->Node.ln_Name && strcmp(name, mh->Node.ln_Name) == 0)
break;
}
if (!mh) {
UnLockAddr(mh);
return(-1);
}
/* Prevent further opens & flag for removal */
FreeMem(mh->Node.ln_Name, strlen(mh->Node.ln_Name)+1);
mh->Node.ln_Name = NULL;
func = mh->IoCtlFunc;
mh->IoCtlFunc = NULL;
/* Call _IOC_DELETE if no more references & delete */
UnLockAddr(Lock);
fioctl(func, _IOC_DELETE, NULL, 0);
if (mh->Refs == 0) {
Remove(mh);
FreeMem(mh, sizeof(MHAN));
return(0);
}
return(1);
}
HAN *
lIoOpen(name, arg1, arg2)
char *name;
ulong arg1, arg2;
{
register MHAN *mh;
register HAN *han;
LockAddr(Lock);
for (mh = GetHead(&MList); mh; mh = GetSucc(mh)) {
if (mh->Node.ln_Name && strcmp(name, mh->Node.ln_Name) == 0)
break;
}
if (!mh) {
UnLockAddr(Lock);
return(NULL);
}
if (!(han = AllocMem(mh->HanSize, MEMF_CLEAR|MEMF_PUBLIC))) {
UnLockAddr(Lock);
return(NULL);
}
++mh->Refs;
UnLockAddr(Lock);
han->MHan = mh;
if (IoCtl(han, _IOC_OPEN, arg1, arg2) == -1) {
FreeMem(han, mh->HanSize);
LockAddr(Lock);
if (--mh->Refs == 0 && mh->Node.ln_Name == NULL) {
Remove(mh);
FreeMem(mh, sizeof(MHAN));
}
UnLockAddr(Lock);
return(NULL);
}
UnLockAddr(Lock);
return(han);
}
lIoClose(han)
register HAN *han;
{
register MHAN *mh = han->MHan;
long hansize = mh->HanSize;
IoCtl(han, _IOC_CLOSE, NULL, NULL); /* finishup */
LockAddr(Lock);
if (--mh->Refs == 0 && mh->Node.ln_Name == NULL) {
Remove(mh);
FreeMem(mh, sizeof(MHAN));
}
UnLockAddr(Lock);
FreeMem(han, hansize);
return(0);
}
#asm
; IoCtl(han:D0, cmd:D1, buf:D2, bytes:A0)
;
; (1) Call IoctlFunc if it exists, (*func)(han,cmd,buf,bytes)
; (2) else call internal function or if IoctlFunc returns -1
public _lIoCtl
public _AutoFunc
_lIoCtl:
addq.l #8,D0 ; skip handle header
movem.l D2/D3/A4/A5/A6,-(sp) ; C compatibility
movem.l D0/D1/D2/A0,-(sp) ; function call params
move.l D0,A0
move.l -4(A0),A0 ; A0 = master handle
move.l MHA_IOCTLFUNC(A0),A1 ; A1 = function to call
move.l A1,D0 ; NULL function
beq .iocn
jsr (A1)
cmp.l #-1,D0 ; result -1 ?
bne .iocr
.iocn lea _AutoFunc,A1 ; error, try internal func
jsr (A1)
.iocr lea 16(sp),sp
movem.l (sp)+,D2/D3/A4/A5/A6
rts
; fioctl(func, cmd, buf1, buf2) .. called as: (NULL,cmd,buf1,buf2)
; (i.e. handleless)
_fioctl: movem.l 4(sp),D0/D1/A0/A1 ; get stack args
movem.l D2/D3/A4/A5/A6,-(sp) ; save regs that might get trashed
move.l D0,A6 ; function to call
moveq.l #0,D0 ; (usually is the handle)
movem.l D0/D1/A0/A1,-(sp) ; push args
jsr (A6) ; make call
lea 16(sp),sp ; pop args
movem.l (sp)+,D2/D3/A4/A5/A6 ; restore regs
rts
#endasm
AutoFunc(han, cmd, arg1, arg2)
register HAN *han;
ulong cmd, arg1, arg2;
{
han = (HAN *)((char *)han - 8);
switch(cmd) {
case IOC_GETFUNC:
return ((long)han->MHan->IoCtlFunc);
case IOC_SETFUNC:
han->MHan->IoCtlFunc = (FPTR)arg1;
return(0);
case IOC_DEVCLAS:
return(0);
case IOC_DUP:
{
register long hansize = han->MHan->HanSize;
register HAN *new = AllocMem(hansize, MEMF_PUBLIC);
register long res;
if (new) {
BMov(han, new, hansize);
res = IoCtl(new, _IOC_DUP, arg1, arg2);
if (res != -1)
return((long)new);
FreeMem(new, hansize);
}
}
break;
}
return(-1);
}
\Rogue\Monster\
else
echo "will not over write notinlib/ioctl.c"
fi
if [ `wc -c notinlib/ioctl.c | awk '{printf $1}'` -ne 5581 ]
then
echo `wc -c notinlib/ioctl.c | awk '{print "Got " $1 ", Expected " 5581}'`
fi
if `test ! -s notinlib/muldiv.asm`
then
echo "writing notinlib/muldiv.asm"
cat > notinlib/muldiv.asm << '\Rogue\Monster\'
;FUNC= MulDiv D0/D1/D2
;FUNC= UMulDiv D0/D1/D2
;FUNC= MulShift D0/D1/D2
;FUNC= UMulShift D0/D1/D2
; MulDiv (a ,b ,c) 32x32->64 64/32->32 (signed)
; MulShift(a ,b ,n) 32x32->64 64>>n->32 (signed)
; D0,D1,D2
;
; 32x32->64 64/32->32
; 32x32->64 64>>n->32
;
; note: n is a word
public _MulDiv
public _UMulDiv
public _MulShift
public _UMulShift
; Various connotations specifying which arguments are
; unsigned (you gain a bit when using unsigned arguments)
REGS eqr D2-D7
_UMulDiv movem.l REGS,-(sp)
clr.w D7
bra .md10
_MulDiv movem.l REGS,-(sp)
clr.w D7
tst.l D0
bpl .md2
neg.l D0
tst.l D1 ; neg
bpl .md1 ; neg
neg.l D1
tst.l D2 ; neg neg
bpl .md10 ; neg neg
neg.l D2
bra .md9 ; neg neg neg
.md1 tst.l D2 ; neg
bpl .md9 ; neg
neg.l D2
bra .md10 ; neg neg
.md2 tst.l D1
bpl .md3
neg.l D1
tst.l D2 ; neg
bpl .md9 ; neg
neg.l D2
bra .md10 ; neg neg
.md3 tst.l D2
bpl .md10
neg.l D2
bra .md9
_UMulShift movem.l REGS,-(sp)
clr.w D7
bra .md6
_MulShift movem.l REGS,-(sp)
clr.w D7
tst.l D0
bpl .md4
neg.l D0
tst.l D1
bpl .md5
neg.l D0
bra .md6
.md4 tst.l D1
bpl .md6
neg.l D1
.md5 addq.w #1,D7
.md6 swap D0
swap D1
tst.w D0
beq .md601
bsr .md0huge
beq .md602a
bra .md603
.md601 tst.w D1
beq .md602
bsr .md1huge
beq .md602a
bra .md603
.md602 swap D0
swap D1
mulu D1,D0
.md602a lsr.l D2,D0
bra .mddone
.md603 subq.w #1,D2
bmi .mddone
.md604 lsr.l #1,D3
roxr.l #1,D0
dbf D2,.md604
bra .mddone
.md10 swap D0
swap D1
tst.w D0
beq .md101
bsr .md0huge
beq .mdsdiv
bsr div64
bra .mddone
.md101 tst.w D1
beq .md105
bsr .md1huge
beq .mdsdiv
bsr div64
bra .mddone
.md105 swap D0 ; both word sized
swap D1
mulu D1,D0 ; D1.WxD0.W -> D0.L
.mdsdiv move.l D2,D1
jsr .divu#
;
;
.md9 addq.w #1,D7
; All elements now unsigned, D7.W determines whether to
; negate at end.
.mddone btst.l #0,D7
beq .mddone2
neg.l D0
.mddone2 movem.l (sp)+,REGS
rts
; NOTE: entered with register halves reversed
;
; D2 not effected
; Test D3 on return
.md0huge tst.w D1
beq .md1hugex ; D0.L, D1.W
; D0.L, D1.L (long x long)
move.w D0,D4 ; save ah
move.w D0,D3 ; ah bh
mulu.w D1,D3
swap D0 ; al bh
move.w D0,D5
mulu.w D1,D5
swap D1
mulu.w D1,D0 ; al bl
mulu.w D4,D1 ; ah bl
add.l D1,D5 ; combine blah and bhal
bcc .mud1
add.l #$10000,D3
.mud1 swap D0 ; LSB MSB
add.w D5,D0
swap D0
clr.w D5
swap D5
addx.l D5,D3 ;64 bit mul result: D3|D0
rts ;Test D3
; D2 not effected
.md1huge exg D0,D1
.md1hugex
; D0.L, D1.W al ah
; bl
move.w D0,D3
mulu.w D1,D3 ; D3 = bl x ah
swap D0
mulu.w D1,D0 ; D0 = bl x al
swap D0 ; add lsb byte of D3 to msb byte of D0
add.w D3,D0
swap D0
clr.w D3 ; doesn't effect X
swap D3 ; msb of D3 actually lsb of second longword
moveq.l #0,D1
addx D1,D3 ; possible x(carry) from previous addition
; 64 bit mul result: D3|D0
; Test D3
rts
; DIV64
;
; 64/32->32 D3|D0 / D2 -> D0
div64:
move.l #0,A0 ;Divide! D1 into D3|D0, D2 = cntr, A0 = rslt
move.w #31,D2 ;(no initial compare). 31 + 1 iterations
.mud10 adda.l A0,A0 ;shift result left
asl.l #1,D0 ;Shift left
roxl.l #1,D3
cmp.l D1,D3
blo .mud11 ;if D3 < D1, skip
sub.l D1,D3 ; D3 >= D1
addq.l #1,A0 ;result = result | 1
.mud11 dbf D2,.mud10
; If remainder (D3) larger than 1/2 C (D1 >> 1), then
; round up result.
lsr.l #1,D1
cmp.l D1,D3
blo .mud12 ; skip if remainder < 1/2C
addq.l #1,A0
.mud12
move.l A0,D0 ;return result
rts
\Rogue\Monster\
else
echo "will not over write notinlib/muldiv.asm"
fi
if [ `wc -c notinlib/muldiv.asm | awk '{printf $1}'` -ne 4567 ]
then
echo `wc -c notinlib/muldiv.asm | awk '{print "Got " $1 ", Expected " 4567}'`
fi
if `test ! -d src`
then
mkdir src
echo "mkdir src"
fi
if `test ! -s src/qint.asm`
then
echo "writing src/qint.asm"
cat > src/qint.asm << '\Rogue\Monster\'
; QINT.ASM
;
; handle= OpenQInts()
; CloseQInts(handle:A0)
; SetQPri(handle:D0, pri:D1)
; SetQVector(handle:D0, vector:D1, signo:D2, arg:D3, pri:A0)
public _lOpenQInts
public _lCloseQInts
public _lSetQPri
public _lSetQVector
public _LVOFindTask
public _LVOAllocMem
public _LVOFreeMem
public _LVOForbid
public _LVOPermit
public _LVODisable
public _LVOEnable
public _LVOEnqueue
public _LVORemove
public _LVOSetSignal
public _LVOSetExcept
QINT_SIZE EQU 32
QINT_NODE EQU 0
QINT_VECTOR EQU 14
QINT_SIGMASK EQU 18
QINT_ARG EQU 22
QINT_UNUSED EQU 26
HAN_SIZE EQU 36+32*QINT_SIZE
HAN_A4 EQU 0
HAN_A5 EQU 4
HAN_EXCODE EQU 8
HAN_EXDATA EQU 12
HAN_INTS EQU 16
HAN_INHAN EQU 18
HAN_PRI EQU 20
HAN_LIST EQU 22
HAN_QINT EQU 36
MEMF_CLEAR EQU $10000
MEMF_PUBLIC EQU $1
LH_HEAD EQU 0
LH_TAIL EQU 4
LH_TAILPRED EQU 8
LN_TYPE EQU 8
LN_PRI EQU 9
TC_EXCEPTCODE EQU 42
TC_EXCEPTDATA EQU 38
_lOpenQInts:
movem.l D2/D3/A2/A6,-(sp)
move.l 4,A6
move.l #HAN_SIZE,D0
move.l #MEMF_CLEAR|MEMF_PUBLIC,D1
jsr _LVOAllocMem(A6)
tst.l D0
beq .oqi1
move.l D0,A2
move.b #-128,HAN_PRI(A2)
movem.l A4/A5,HAN_A4(A2)
lea.l HAN_LIST+LH_HEAD(A2),A0
lea.l HAN_LIST+LH_TAIL(A2),A1
move.l A1,(A0)
move.l A0,LH_TAILPRED(A0)
.oqi1 movem.l (sp)+,D2/D3/A2/A6
rts
_lCloseQInts: ; A0 = handle
movem.l D2/D3/A2/A6,-(sp)
move.l 4,A6
move.l A0,A2 ; A2 = handle
move.l A0,D0 ; skip if null
beq .cqi1
moveq.l #31,D3 ; D3 = sig number.
.cqi2 move.w D3,-(sp)
move.l D3,D2 ; SetQVector(han, NULL, sig#, 0, 0)
move.l A2,D0 ; D0 D1 D2 D3 A0
moveq.l #0,D1
move.l D1,D3
move.l D1,A0
jsr _lSetQVector
move.w (sp)+,D3
dbf D3,.cqi2
.cqi1 movem.l (sp)+,D2/D3/A2/A6
rts
; _EXCEPT , Exception handler.
;
;entry:
; D0 = exceptions that occured
; A1 = Handle
;
;auto:
; A2 = Handle
; A4/A5 = Possible Global Base Registers
; D4 = Bit# count
; D6 = Exceptions that occured
_except:
move.l 4,A6 ;A6 = Exec Base
move.l D0,D6 ;D6 = Exception Bit Mask
movem.l HAN_A4(A1),A4/A5;get global base register(s).
move.l A1,A2 ;A2 = HANDLE BASE
; Queue any exceptions which are interrupts. Exceptions
; for interrupts which are queued are NOT reenabled until
; they are actually run.
;
; Note that in the loop we must loop to .ex2 to decrement
; D4, which doesn't occur when we find a '1'. The Z bit
; must be set when we loop to .ex2
.ex0 moveq.l #31,D4 ;D4 = BIT NUMBER
.ex1 btst.l D4,D6 ; test bits
.ex2 dbne D4,.ex1 ; until found a '1'
beq .ex10 ;or loop exhausted (D4 == -1)
move.l D4,D5 ;Calculate address of QINT.
asl.l #5,D5 ;D5 = index * sizeof(QINT)
pea.l HAN_QINT(A2)
add.l (sp)+,D5 ; + Base of QINT array
move.l D5,A3 ;A3 = QINT address
tst.l QINT_VECTOR(A3) ;Is this exception vectored?
beq .ex2 ;no, somebody else owns it
.ex3 bclr.l D4,D6 ;clear exception bit.
jsr _LVOForbid(A6) ;Important operation!
move.l A3,A1 ;A1 = node
lea.l HAN_LIST(A2),A0 ;A0 = List Base
move.b #5,LN_TYPE(A1) ;mark node as being queued
jsr _LVOEnqueue(A6)
jsr _LVOPermit(A6) ;enable exceptions
clr.w D7 ;Force Z cc set.
bra .ex2 ;loop (force decrement/loop)
; Call the handler. The handler is allowed to trash
; everything except D6/A7. Called with A2 = Handle,
; A6 = Exec Base
.ex10 tst.w HAN_INHAN(A2) ;no need to call handler?
bne .ex11
bsr _handler ;call handler
.ex11 move.l D6,D0 ;D0 = exception mask
beq .ex12 ;we processed all exceptions
move.l HAN_EXCODE(A2),A0 ;somebody else owns some exceptions
move.l HAN_EXDATA(A2),A1 ;restore exception data pointer
jmp (A0) ;call him with remaining exceptions.
.ex12 rts
;entry:
; A2 = Handle
; A4/A5 = Possible Global Base Registers
; A6 = EXEC base
;
;auto:
; A2 = Handle;
; A3 = Qint
; A4/A5 = GBRs
; A6 = EXEC base
; D4 = savepri
_handler:
move.b #1,HAN_INHAN(A2)
jsr _LVOForbid(A6)
.hloop move.l HAN_LIST+LH_HEAD(A2),A3
lea.l HAN_LIST+LH_TAIL(A2),A0
cmp.l A0,A3 ;List is empty
beq .hbreak
move.b HAN_PRI(A2),D4 ;Check priority of node
cmp.b QINT_NODE+LN_PRI(A3),D4
bgt .hbreak ;savepri > qintpri
move.l A3,A1 ;A1 = node to remove
jsr _LVORemove(A6)
move.b #0,QINT_NODE+LN_TYPE(A3)
move.b QINT_NODE+LN_PRI(A3),HAN_PRI(A2)
jsr _LVOPermit(A6)
move.l QINT_ARG(A3),-(sp)
move.l QINT_VECTOR(A3),A0
jsr (A0)
move.l 4,A6
addq.l #4,sp
move.b D4,HAN_PRI(A2)
tst.l QINT_VECTOR(A3) ;Reenable the exception
beq .h1 ;only if the vector still
move.l QINT_SIGMASK(A3),D0 ;exists.
move.l D0,D1
jsr _LVOSetExcept(A6)
.h1 jsr _LVOForbid(A6)
bra .hloop
.hbreak moveq.l #0,D2
move.b D2,HAN_INHAN(A2)
jsr _LVOPermit(A6)
move.l D2,D0
move.l D2,D1
jsr _LVOSetExcept(A6)
rts
; SetQVector()
;
; D0 = handle (copy to A2)
; D1 = vector (copy to A3)
; D2 = signo
; D3 = arg (copy to D5)
; A0 = pri
;
; A2 = handle
; A3 = vector
; A4 = qint
; A5 = task
;
; D2 = pri
; D3 = sigmask
; D4 = oldvector
; D5 = arg
; D6 =
; D7 =
_lSetQVector:
movem.l D2-D7/A2-A6,-(sp)
move.l 4,A6
move.l D0,A2 ; A2 = Handle
move.l D1,A3 ; A3 = Vector
move.l D3,D5 ; D5 =
moveq.l #0,D3 ; D3 = signal mask
bset.l D2,D3 ; D2 = signal
asl.l #5,D2 ; A4 = qint (han->QInt + signo)
add.l #HAN_QINT,D2
add.l A2,D2
move.l D2,A4 ; A4 = QINT
move.l A0,D2 ; D2 = priority
move.w #0,A1 ; A5 = task
jsr _LVOFindTask(A6)
move.l D0,A5
jsr _LVOForbid(A6) ; Forbid
move.l QINT_VECTOR(A4),D4 ; D4 = oldvector
move.l A3,D0
bne .sq100
; If new vector is NULL, remove old vector if it exists.
tst.l D4
beq .sqdone
moveq.l #0,D0
move.l D3,D1
jsr _LVOSetExcept(A6)
cmp.b #5,QINT_NODE+LN_TYPE(A4)
bne .sq1
move.l A4,A1
jsr _LVORemove(A6)
move.b #0,QINT_NODE+LN_TYPE(A4)
.sq1 sub.w #1,HAN_INTS(A2)
bne .sq2
jsr _LVODisable(A6)
move.l HAN_EXCODE(A2),TC_EXCEPTCODE(A5)
move.l HAN_EXDATA(A2),TC_EXCEPTDATA(A5)
jsr _LVOEnable(A6)
.sq2 bra .sqdone
; If new vector not null, replace (possibly NULL) old vector
.sq100 tst.l D4
bne .sq150
add.w #1,HAN_INTS(A2) ; oldvector is null, setup task
cmp.w #1,HAN_INTS(A2)
bne .sq150
jsr _LVODisable(A6)
move.l TC_EXCEPTCODE(A5),HAN_EXCODE(A2)
move.l TC_EXCEPTDATA(A5),HAN_EXDATA(A2)
move.l #_except,TC_EXCEPTCODE(A5)
move.l A2,TC_EXCEPTDATA(A5)
jsr _LVOEnable(A6)
.sq150 move.l D5,QINT_ARG(A4)
move.b D2,QINT_NODE+LN_PRI(A4)
move.l D3,QINT_SIGMASK(A4)
move.l D3,D0
move.l D3,D1
jsr _LVOSetExcept(A6)
bra .sqdone
.sqdone move.l A3,QINT_VECTOR(A4)
jsr _LVOPermit(A6)
moveq.l #0,D0
move.l D0,D1
jsr _LVOSetExcept(A6)
move.l D4,D0
movem.l (sp)+,D2-D7/A2-A6
rts
; SetQPri
;
; D0 = handle
; D1 = newpri
;
; A2 = handle
; D2 = newpri
; D3 = oldpri
_lSetQPri:
movem.l D2/D3/A2/A6,-(sp)
move.l 4,A6
move.l D0,A2
move.l D1,D2
jsr _LVODisable(A6)
move.b HAN_PRI(A2),D3
move.b D2,HAN_PRI(A2)
jsr _LVOEnable(A6)
cmp.b D2,D3
ble .sqpdone ; D3 <= D2 (old <= new)
lea.l HAN_LIST+LH_TAIL(A2),A0
cmp.l HAN_LIST+LH_HEAD(A2),A0
beq .sqpdone
movem.l D4/A3,-(sp)
jsr _handler ;A2 = handle, A6 = execbase
movem.l (sp)+,D4/A3
.sqpdone:
moveq.l #0,D0
move.b D3,D0
movem.l (sp)+,D2/D3/A2/A6
rts
\Rogue\Monster\
else
echo "will not over write src/qint.asm"
fi
if [ `wc -c src/qint.asm | awk '{printf $1}'` -ne 8366 ]
then
echo `wc -c src/qint.asm | awk '{print "Got " $1 ", Expected " 8366}'`
fi
if `test ! -s src/ires.h`
then
echo "writing src/ires.h"
cat > src/ires.h << '\Rogue\Monster\'
/*
* Internal Resource Header Files
*/
#define TML struct _TML
#define TREN struct _TREN
#define SVS struct _SVS
#define RFILE struct _RFILE
#define FTABLE struct _FTABLE
#define HTABLE struct _HTABLE
/*
* Task Mem-List Resource structure
*/
TML {
long XLock[2];
MLIST RENList; /* List of resources */
MLIST RFList; /* List of private resource Files */
};
/*
* Task Resource Entry
*/
TREN {
MNODE Node;
APTR Ptr;
long (*Func)();
};
/*
* Swap Volume Structure
*/
SVS {
MNODE Node;
long XLock[2];
long Fh; /* associated fh or lock */
uword Flags; /* HAVHANDLE, HAVLOCK */
long Swapped; /* bytes swapped */
long FileSize; /* current file size */
long Free; /* bytes free */
long Link[32]; /* swap area free lists */
char *Name; /* swap volume name */
};
/*
* Resource File Structure
*/
RFILE {
MNODE Node;
long XLock[2];
long Fh; /* associated fh or lock */
long HTsize; /* hash table size in file */
long Loaded; /* bytes loaded */
long Swapped; /* bytes swapped */
uword Flags; /* HAVHANDLE, HAVLOCK */
uword HTSize; /* pwr of 2, # of entries */
FTABLE **HTab; /* [n]&3:0-mem 1-seek. file access dict. */
HTABLE **LTab; /* active resource access table (by name) */
char *Name; /* resource file name */
};
/*
* Hash table entry for dictionary
*/
FTABLE {
long Next; /* Next entry 0-end, &3:0-mem 1-seek */
uword Flags; /* all applicable flags, inc load state */
ubyte NLen; /* name length */
ubyte TLen; /* type length */
long Seek; /* seek position in file */
long Len; /* size of resource in file / htable ptr */
ubyte Name[2]; /* extend structure to [n] */
};
/*
* Hash table entry for active resource
*/
HTABLE {
long Next; /* Next entry 0-end, &3:0-mem 1-swapped */
uword Flags; /* all applicable flags, inc load state */
uword Refs;
long Ptr; /* data ptr, swap ptr */
long Func; /* control function */
};
\Rogue\Monster\
else
echo "will not over write src/ires.h"
fi
if [ `wc -c src/ires.h | awk '{printf $1}'` -ne 2194 ]
then
echo `wc -c src/ires.h | awk '{print "Got " $1 ", Expected " 2194}'`
fi
if `test ! -s src/lists.asm`
then
echo "writing src/lists.asm"
cat > src/lists.asm << '\Rogue\Monster\'
; EXTENDED LIST/NODE HANDLING
;
; (C)CopyRight May 1988, Matthew Dillon, All Rights Reserved
;
;NOTE: These routines accomodate structures where the
; NODE used to traverse the list is not necessarily
; at the beginning of the structure. This, 'sptr'
; refers to the structure pointer (not the node
; pointer, unless the node is at the beginning), and
; 'off' offset refers to the offset into the structure
; where the NODE resides.
public _lGetHead ; node = GetHead(list)
public _lGetTail ; node = GetTail(list)
public _lGetSucc ; node = GetSucc(node)
public _lGetPred ; node = GetPred(node)
public _lGetHeadOff ; sptr = GetHeadOff(list, off)
public _lGetTailOff ; sptr = GetTailOff(list, off)
public _lGetSuccOff ; sptr = GetSuccOff(sptr, off)
public _lGetPredOff ; sptr = GetPredOff(sptr, off)
public _lEnqueueLong ; (void)EnqueueLong(list, start, sptr, valoff)
public _lEnqueueOffLong ; (void)EnqueueOffLong(list, start, sptr, off, valoff)
public _lSearchFwdNode ; ret = SearchFwdNode(sptr, func, arg) -> func(somesptr,arg)
public _lSearchRvsNode ; ret = SearchRvsNode(sptr, func, arg) (ditto)
public _lSearchFwdList ; ret = SearchFwdList(list, func, arg) (ditto)
public _lSearchRvsList ; ret = SearchRvsList(list, func, arg) (ditto)
public _lSearchFwdNodeOff ; ret = SearchFwdNode(sptr, func, off, arg) -> func(somesptr,arg)
public _lSearchRvsNodeOff ; ret = SearchRvsNode(sptr, func, off, arg) (ditto)
public _lSearchFwdListOff ; ret = SearchFwdList(list, func, off, arg) (ditto)
public _lSearchRvsListOff ; ret = SearchRvsList(list, func, off, arg) (ditto)
; GETHEAD(list:A0)
; GETSUCC(node:A0)
_lGetSucc:
_lGetHead: move.l (A0),A0
tst.l (A0)
beq .gh0
move.l A0,D0
rts
; GETTAIL(list:A0)
_lGetTail: move.l 8(A0),A0
tst.l 4(A0)
beq .gh0
move.l A0,D0
rts
; GETPRED(node:A0)
_lGetPred: move.l 4(A0),A0
tst.l 4(A0)
beq .gh0
move.l A0,D0
rts
.gh0 moveq.l #0,D0
rts
; GETHEADOFF(list:D0, offset:D1)
_lGetHeadOff: move.l D0,A0
move.l (A0),A0
tst.l (A0)
beq .gh0
sub.l D1,A0
move.l A0,D0
rts
; GETTAILOFF(list:D0, offset:D1)
_lGetTailOff: move.l D0,A0
move.l 8(A0),A0
tst.l 4(A0)
beq .gh0
sub.l D1,A0
move.l A0,D0
rts
; SPTR is a structure pointer, where the node is offset
; OFFSET from the base of the structure.
; GETSUCCOFF(sptr:D0, offset:D1)
_lGetSuccOff: move.l D0,A0
move.l (A0,D1.L),A0
tst.l (A0)
beq .gh0
suba.l D1,A0
move.l A0,D0
rts
; GETPREDOFF(sptr:D0, offset:D1)
_lGetPredOff: move.l D0,A0
move.l 4(A0,D1.L),A0
tst.l 4(A0)
beq .gh0
suba.l D1,A0
move.l A0,D0
rts
; ENQUEUELONG(list:D0, start:D1, sptr:D2, valoff:D4)
; ENQUEUEOFFLONG(list:D0, start:D1, sptr:D2, off:D3, valoff:D4)
;
; list: list to queue the object in
; start: sptr to start search at (NULL=beginning of list)
; sptr: pointer to the structure to queue, where
; off: offset into the structure where the embedded Node is
; valoff: offset into structure where the longword holding
; the sorting priority of the object is.
;
; The list is already assumed to be sorted. The search
; progresses either forward or reverse along the list until
; the proper place is found, then the object is inserted into
; the list. The object is placed AFTER any objects of equal
; priority (whether the list is searched forward or backwards).
_lEnqueueLong:
movem.l D3/A2/A3,-(sp)
moveq.l #0,D3
bra .eol1
_lEnqueueOffLong:
movem.l D3/A2/A3,-(sp)
.eol1 move.l D2,A3 ; A3 = structure to add
move.l D1,A2 ; A2 = roving structure in search
tst.l D1
bne .eol2
move.l D0,A2 ; use list head instead
move.l (A2),A1
tst.l (A1)
beq .eol100 ; add structure to empty list
move.l A1,A2
sub.l D3,A2 ; retrieve structure pointer
; D0 = D4(A3)
; D3 = offset into A2/A3 of node
; D4 = offset into A2/A3 of longword value
; A2 = roving structure ptr
; A3 = structure to add
;
; Sequence: if D4(A3) > D4(A2), forward search
; if D4(A3) < D4(A2), reverse search
.eol2 move.l (A3,D4.L),D0 ; Search forwards or backwards?
cmp.l (A2,D4.L),D0
blt .eol50
.eol10 move.l (A2,D3.L),A2 ; SEARCH FORWARDS (A2 = next node)
tst.l (A2) ; reached list tail
beq .eol30 ; Add to tail
sub.l D3,A2 ; A2 = structure
cmp.l (A2,D4.L),D0
bge .eol10 ; loop while value > roving_value
add.l D3,A2 ; ADDBEFORE current node, A2 = listnode
add.l D3,A3 ; A3 = node to add
move.l A2,(A3) ; INSERT BEFORE (listnode:A2, node:A3)
move.l 4(A2),A0 ; A0 is node before A2 (seq A0-A3-A2)
move.l A0,4(A3)
move.l A3,4(A2)
move.l A3,(A0)
bra .eolend
; (A2 points to lh_Tail here)
.eol30 move.l 4(A2),A2 ; ADDTOEND, A2 = tail element
bra .eol100
.eol50 move.l 4(A2,D3.L),A2 ;SEARCH BACKWARDS (A2 = prev. node)
tst.l 4(A2) ;reached list head .. AddHead()
beq .eol100
sub.l D3,A2 ;A2 = structure pointer
cmp.l (A2,D4.L),D0 ;loop while value < roving_value
blt .eol50
add.l D3,A2 ;add after NODE A2
.eol100 add.l D3,A3 ;INSERT AFTER(list/node:A2, structure:A3)
move.l (A2),A0
move.l A0,(A3)
move.l 4(A0),4(A3)
move.l A3,(A2)
move.l A3,4(A0)
.eolend movem.l (sp)+,D3/A2/A3
rts
; SEARCHFWDLIST[OFF](list:D0, func:D1, [offset:A0,] funcarg:A1)
; SEARCHRVSLIST[OFF](list:D0, func:D1, [offset:A0,] funcarg:A1)
;
; Get head/tail of list then call Search???Node
_lSearchFwdList:
sub.l A0,A0
_lSearchFwdListOff:
movem.l D2-D5/A2/A3/A6,-(sp)
move.l D0,A2
move.l (A2),A2 ; get head of list
tst.l (A2) ; empty list?
bne SFN
bra .sfn0
_lSearchRvsList:
sub.l A0,A0
_lSearchRvsListOff:
movem.l D2-D5/A2/A3/A6,-(sp)
move.l D0,A2
move.l 8(A2),A2 ; get tail of list
tst.l 4(A2) ; empty list?
bne SRN
bra .sfr0
; For compatibility with various C compilers, neither
; A4 or A5 is touched. D2,D3, and A6 are also assumed
; to be destroyed by the function.
;
; The search ends when the function returns a non-NULL
; value or the list is exhausted (NULL is returned)
;
; SEARCHFWDNODE(sptr:D0, func:D1, offset:A0, funcarg:A1)
_lSearchFwdNode:
sub.l A0,A0
_lSearchFwdNodeOff:
movem.l D2-D5/A2/A3/A6,-(sp)
move.l D0,A2
SFN: move.l D1,A3
move.l A0,D4
move.l A1,D5
move.l A2,D0 ; test for initial NULL
beq .sfndone
adda.l D4,A2
.sfnloop suba.l D4,A2
move.l D5,-(sp) ; call function(sptr, funcarg)
move.l A2,-(sp)
jsr (A3)
addq.l #8,sp
tst.l D0 ; non-zero ret. value
bne .sfndone
adda.l D4,A2 ; GetSuccOff()
move.l (A2),A2
tst.l (A2)
bne .sfnloop
.sfn0 moveq.l #0,D0
.sfndone movem.l (sp)+,D2-D5/A2/A3/A6
rts
; SEARCHRVSNODE(node:D0, func:D1, offset:A0, funcarg:A1)
_lSearchRvsNode:
sub.l A0,A0
_lSearchRvsNodeOff:
movem.l D2-D5/A2/A3/A6,-(sp)
move.l D0,A2
SRN: move.l D1,A3
move.l A0,D4
move.l A1,D5
move.l A2,D0 ; test for initial NULL
beq .sfrdone
adda.l D4,A2
.sfrloop suba.l D4,A2
move.l D5,-(sp) ; call function(sptr, funcarg)
move.l A2,-(sp) ; args also in A2 and D5
jsr (A3)
addq.l #8,sp
tst.l D0 ; non-zero ret. value
bne .sfrdone
adda.l D4,A2 ; GetPredOff()
move.l 4(A2),A2
tst.l 4(A2)
bne .sfrloop
.sfr0 moveq.l #0,D0
.sfrdone movem.l (sp)+,D2-D5/A2/A3/A6
rts
\Rogue\Monster\
else
echo "will not over write src/lists.asm"
fi
if [ `wc -c src/lists.asm | awk '{printf $1}'` -ne 7630 ]
then
echo `wc -c src/lists.asm | awk '{print "Got " $1 ", Expected " 7630}'`
fi
if `test ! -s src/timedate.c`
then
echo "writing src/timedate.c"
cat > src/timedate.c << '\Rogue\Monster\'
/*
* DATETOS.C
*
* leap year: every four years but 3 out of 4 century marks are not leap years
* (2000 is) the year 0 was. year&3==0 is
* timestamp is since 1978
*
* valid range: Jan 1 1976 to Dec 31 2099
*/
#include <local/typedefs.h>
static char dim[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
static char *Month[12] = { "Jan","Feb","Mar","Apr","May","Jun","Jul",
"Aug","Sep","Oct","Nov","Dec" };
char *
lDateToS(date, str, ctl)
DATESTAMP *date;
char *str;
char *ctl;
{
long days, years;
short leap, month;
if (ctl == NULL)
ctl = "D M Y h:m:s";
days = date->ds_Days + 731; /* 1976 */
years = days / (365*3+366); /* #quad yrs */
days -= years * (365*3+366);
leap = (days < 366); /* is a leap yr*/
years = 1976 + 4 * years;
if (!leap) {
days -= 366;
++years;
}
years += days / 365;
days -= (days / 365) * 365;
for (month = 0; (month==1) ? (days >= 28 + leap) : (days >= dim[month]); ++month)
days -= (month==1) ? (28 + leap) : dim[month];
{
register short i = 0;
for (; *ctl; ++ctl) {
switch(*ctl) {
case 'h':
utos(str+i, 1, 2, date->ds_Minute / 60);
/*sprintf(str+i, "%02d", date->ds_Minute / 60);*/
break;
case 'm':
utos(str+i, 1, 2, date->ds_Minute % 60);
/*sprintf(str+i, "%02d", date->ds_Minute % 60);*/
break;
case 's':
utos(str+i, 1, 2, date->ds_Tick / 50 % 60);
/*sprintf(str+i, "%02d", date->ds_Tick / 50 % 60);*/
break;
case 'Y':
utos(str+i, 0, 4, years);
/*sprintf(str+i, "%ld", years);*/
break;
case 'M':
strcpy(str+i, Month[month]);
break;
case 'D':
utos(str+i, 0, 2, days+1);
/*sprintf(str+i,"%2ld", days+1);*/
break;
default:
str[i] = *ctl;
str[i+1] = 0;
break;
}
i += strlen(str+i);
}
}
return(str);
}
utos(buf, zfill, flen, val)
register char *buf;
register short flen;
{
buf[flen] = 0;
while (flen--) {
if (val)
buf[flen] = '0' + (val % 10);
else
buf[flen] = (zfill) ? '0' : ' ';
val /= 10;
}
}
#define BTOC(bptr) ((long)(bptr) << 2)
#define CTOB(cptr) ((long)(cptr) >> 2)
#ifndef ACTION_SET_DATE
#define ACTION_SET_DATE 34
#endif
typedef struct StandardPacket STDPKT;
typedef struct MsgPort MSGPORT;
extern void *AllocMem();
lSetFileDate(file, date)
char *file;
DATESTAMP *date;
{
register STDPKT *packet;
register char *buf;
register PROC *proc;
long result;
long lock;
{
register long flock = Lock(file, SHARED_LOCK);
register short i;
register char *ptr = file;
if (flock == NULL)
return(NULL);
lock = ParentDir(flock);
UnLock(flock);
if (!lock)
return(NULL);
for (i = strlen(ptr) - 1; i >= 0; --i) {
if (ptr[i] == '/' || ptr[i] == ':')
break;
}
file += i + 1;
}
proc = (PROC *)FindTask(NULL);
packet = (STDPKT *)AllocMem(sizeof(STDPKT), MEMF_CLEAR|MEMF_PUBLIC);
buf = AllocMem(strlen(file)+2, MEMF_PUBLIC);
strcpy(buf+1,file);
buf[0] = strlen(file);
packet->sp_Msg.mn_Node.ln_Name = (char *)&(packet->sp_Pkt);
packet->sp_Pkt.dp_Link = &packet->sp_Msg;
packet->sp_Pkt.dp_Port = &proc->pr_MsgPort;
packet->sp_Pkt.dp_Type = ACTION_SET_DATE;
packet->sp_Pkt.dp_Arg1 = NULL;
packet->sp_Pkt.dp_Arg2 = (long)lock; /* lock on parent dir of file */
packet->sp_Pkt.dp_Arg3 = (long)CTOB(buf); /* BPTR to BSTR of file name */
packet->sp_Pkt.dp_Arg4 = (long)date; /* APTR to datestamp structure */
PutMsg(((LOCK *)BTOC(lock))->fl_Task, packet);
WaitPort(&proc->pr_MsgPort);
GetMsg(&proc->pr_MsgPort);
result = packet->sp_Pkt.dp_Res1;
FreeMem(packet, sizeof(STDPKT));
FreeMem(buf, strlen(file)+2);
UnLock(lock);
return(result);
}
\Rogue\Monster\
else
echo "will not over write src/timedate.c"
fi
if [ `wc -c src/timedate.c | awk '{printf $1}'` -ne 3802 ]
then
echo `wc -c src/timedate.c | awk '{print "Got " $1 ", Expected " 3802}'`
fi
if `test ! -s src/oldfile.c`
then
echo "writing src/oldfile.c"
cat > src/oldfile.c << '\Rogue\Monster\'
#include <local/res.h>
#define SFILE struct _SFILE
#define RFILE struct _RFILE
#define FTABLE struct _FTABLE
#define HTABLE struct _HTABLE
SFILE {
long XLock[2];
long Fh; /* associated fh or lock */
uword Flags; /* HAVHANDLE, HAVLOCK */
long Swapped; /* bytes swapped */
long FileSize; /* current file size */
long Free; /* bytes free */
long Link[32]; /* swap area free lists */
char *Name; /* file name */
};
RFILE {
long XLock[2];
long Fh; /* associated fh or lock */
long HTsize; /* hash table size in file */
long Loaded; /* bytes loaded */
long Swapped; /* bytes swapped */
uword Flags; /* HAVHANDLE, HAVLOCK */
uword HTSize; /* pwr of 2, # of entries */
FTABLE **HTab; /* [n]&3:0-mem 1-seek. file access dict. */
HTABLE **LTab; /* active resource access table */
char *Name; /* file name */
};
FTABLE {
long Next; /* Next entry 0-end, &3:0-mem 1-seek */
uword Flags; /* all applicable flags, inc load state */
ubyte NLen; /* name length */
ubyte TLen; /* type length */
long Seek; /* seek position in file */
long Len; /* size of resource in file / htable ptr */
ubyte Name[2]; /* extend structure to [n] */
};
HTABLE {
long Next; /* Next entry 0-end, &3:0-mem 1-swapped */
uword Flags; /* all applicable flags, inc load state */
uword Refs;
long Ptr; /* data ptr, swap ptr */
long Func; /* control function */
};
\Rogue\Monster\
else
echo "will not over write src/oldfile.c"
fi
if [ `wc -c src/oldfile.c | awk '{printf $1}'` -ne 1623 ]
then
echo `wc -c src/oldfile.c | awk '{print "Got " $1 ", Expected " 1623}'`
fi
if `test ! -s src/oldfile.h`
then
echo "writing src/oldfile.h"
cat > src/oldfile.h << '\Rogue\Monster\'
/*
* FILE.H
*
* Message Passing structure.
*/
#define RMSG struct _RMSG
RMSG {
MSG Mesg; /* exec message */
long Arg1;
long Arg2;
long Arg3;
long Arg4;
long Res1;
};
#define RACT_GETRES 1 /* (name,type,nmlen,tylen) */
#define RACT_
extern PORT ResPort;
\Rogue\Monster\
else
echo "will not over write src/oldfile.h"
fi
if [ `wc -c src/oldfile.h | awk '{printf $1}'` -ne 319 ]
then
echo `wc -c src/oldfile.h | awk '{print "Got " $1 ", Expected " 319}'`
fi
if `test ! -s src/res.c`
then
echo "writing src/res.c"
cat > src/res.c << '\Rogue\Monster\'
/*
* RES.C
*
* System Overview:
* GetRes() -
* DupRes() -
* FreeRes() -
* FreeAllRes() -
* ChownRes() -
* UnLinkAllRes() -
* ReLinkAllRes() -
* SetResFlags() -
* AddRes() -
* RemRes() -
* GetResInfo() -
* GetResList() -
* GetFileList() -
* AddPrivResFile() -
* RemPrivResFiles() -
* AddGlobResFile() -
* RemGlobResFiles() -
* AddResSwapDir() -
* RemResSwapDirs() -
*
*/
#include <local/typedefs.h>
#include <local/ipc.h>
#include <local/res.h>
#include "/src/ires.h"
static long SysLock[2] = { 0, 0 };
extern TML *GetTML();
/*
* Search order: Private-mem, Private-disk, System-mem, System-disk,
* OtherTaskGlob-mem, OtherTaskGlob-disk
*/
APTR
GetRes(name)
char *name;
{
TML *tml = GetTML();
resptr= GetRes(resnametype) char *resnametype;
This function retrieves the requested resource, doing any
translations required to get the resource into the requested
type. NULL is returned if the resource could not be found
or could not be translated to the requested type.
In-Memory private resources are searched first, then the private
resource files for the task, then In-Memory system resources, then
the global resource files for the system. Openning an already-open
resource causes one of two actions depending on whether the resource
is shared or not. If shared, the reference count is simply
incremented, otherwise a private copy of the resource is made.
Example: Win = GetRes("Charlie.Window");
resptr2 = DupRes(resptr1) APTR resptr1, resptr2;
This call duplicates a resource. If the resource is shared
resptr2 will be the same as resptr1 and the reference count will
be bumped. Otherwise, a new resource data area is allocated and
the old copied to the new.
Things like fixing pointers and such within a resource that is
physically duplicated are handled by the interface code (since
raw resources do not contain pointers, only VIRTUAL resources
will contain pointers and all VIRTUAL resources have some
interface code).
error = FreeRes(resptr)
Free a resource that you retrieved via GetRes(). Only the task
that owns the resource may free it (though several tasks may own
a resource through duplication and ownership changes). 1 is
returned on success, 0 on error.
That is, if task #1 GetRes()'s the resource and duplicates it once,
then task #2 duplicates it once, task #1 must call FreeRes() twice
and task #2 must call FreeRes() once. Ownership is strictly
tracked.
numres= FreeAllRes(task)
Free all resources associated with the specified task (NULL for
self).
error = ChownRes(resptr, fromtask, totask)
Change ownership of a resource from the source task to the
destination task. The resource must be owned by the source
task or an error will occur (0 return value). 1 is returned
on success. NULL may be specified for either or both tasks
and means the calling task.
handle= UnLinkAllRes(task)
Unlink all resources associated with the specified task (NULL
for self) and return a handle representing those resources.
This is useful for shells and such to keep their resources from
getting removed by commands they run. Combined with the NUNLINK
flag one can pass resources to a Command and keep the rest out of
reach.
(void) ReLinkAllRes(handle, task)
Link all the resources represented by the handle to the specified
task (NULL for self).
oldfl = SetResFlags(resptr, newflags, flagsmask)
Modify the flags associated with a resource. NOTE: If multiple
references to a shared resource exist, all are modified. Some
modifications may be disallowed by the system. This call is
normally used to modify the LOCKED and SWAPABLE flags (note that
the SWAPABLE flag can be changed back and forth only for resource
which support it).
error = AddRes(resnametype, flags, ptr, ctlcode);
char *resnametype;
long flags;
APTR ptr;
long (*ctlcode)();
Add a resource to the system. The resource is placed either in
the task's privately accessable in-memory resource list or
in the system global accessable in-memory resource list depending
on the specified flags. One may now GetRes() the resource.
ONLY VIRTUAL RESOURCES MAY BE ADDED IN THIS WAY. The VIRTUAL
and LOCKED flags are automatically set.
If flags specifies a VIRTUAL resource
error = RemRes(resname)
Remove the specified resource. An error will occur and the resource
will not be removed (1) if it does not exist in memory, or (2) it
is currently being referenced. (Note: the resource is removed even
if it is swapped or locked).
error = GetResInfo(resname, &flags, &bytes)
Get information on a resource. Information may not exist for a
resource if it is not currently in memory and would have to be
translated to get to the right type.
error = GetResList(wildcard, from, &av, &ac);
from: mask, bit 0 search private list
1 search system list
2 <not used>
3 search in-memory private list
4 search in-memory global list
Return an ARGC/ARGV list of resource names. Note that some names
might be duplicated if searching multiple lists. Restricting the
search to in-memory lists give resources which are already in
memory (but might be swapped out or removed at any time for those
with no references)
RESOURCE FILES
error = GetFileList(wildcard, from, &av, &ac);
from: mask, bit 0 search private list
1 search system list
2 search swap list
Return an ARGC/ARGV list of the files which match the specified
wildcard from the private list, system list, or system swap dir
list (in which case you get directory names). This list has been
allocated, and can be freed as follows:
Loop through all entries for (i = 0; i < ac; ++i)
FreeMem(av[i], strlen(av[i])+1);
Free the array itself: FreeMem(av, sizeof(char *) * (ac+1));
num = AddPrivResFile(filename, pri)
Add a file name to the list of resource files for this task. These
are scanned before global files when a resource is requested. All
files in the list are write protected (i.e. a shared lock is kept
for each file). Thus, such files cannot be updated until removed
from the list.
Can also be used to modify the priority of an existing file
num = RemPrivResFiles(wildcard)
Remove zero or more file names from the list of resource files for
this task. A wildcard pattern (* and ?) is accepted.
Note for command processors: commands you run might execute
this command for *.
num = AddGlobResFile(filename, pri)
Same as AddPrivResFile() but applies to the system list, which is
searched last and by any requesting task. Wildcard file names are
NOT accepted. The file need not exist at this time, and references
to unmounted volumes are allowed.
Can also be used to modify the priority of an existing entry
num = RemGlobResFiles(wildcard)
Remove zero or more resource files from the global list. Again,
a wildcard filename is accepted.
num = AddResSwapDir(dirname, pri, maxkbytes) char *dirname;
char pri;
long maxkbytes
Add a directory to the list of directories the resource system
can swap to. The maximum number of KBytes of material allowed
in the directory should be specified. You can also use this
call to modify the priority and maxkbytes for an entry.
The highest priority directories are used before lower priority
directories. Not all directories need be mounted, but if a swapin
occurs from an unmounted directory a requester will appear.
A lock is kept on each specified directory.
num = RemResSwapDirs(wildcard)
Remove directories associated with the resource swap areas.
RESOURCE FILE IFF FORMAT
static
TML *
GetTML()
{
TML *tml = GetTaskData(RESMLNAME, sizeof(TML));
if (tml && !tml->RFList.mlh_Head) {
NewList(&tml->RENList);
NewList(&tml->RFList);
}
return(tml);
}
\Rogue\Monster\
else
echo "will not over write src/res.c"
fi
if [ `wc -c src/res.c | awk '{printf $1}'` -ne 8107 ]
then
echo `wc -c src/res.c | awk '{print "Got " $1 ", Expected " 8107}'`
fi
echo "Finished archive 2 of 3"
# if you want to concatenate archives, remove anything after this line
exit
--
Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page
Have five nice days.